package com.kexio.auth.mybatis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.kexio.auth.config.MybatisPlusProperties;
import com.kexio.auth.config.TenantModeProperties;
import com.kexio.auth.config.TenantModeProperties.TenantMode;

/**
 * 智能的MyBatis-Plus自动配置
 * 
 * 🎯 设计原则：
 * 1. 单一配置源 - 所有拦截器配置集中在一处
 * 2. 配置驱动 - 完全基于配置文件控制行为
 * 3. 智能装配 - 根据环境和配置自动选择最优配置
 * 4. 零配置启用 - 开箱即用，无需额外配置
 * 
 * 🏗️ 支持的拦截器（按优先级顺序）：
 * 1. 租户拦截器（条件性启用）
 * 2. 分页拦截器（总是启用） 
 * 3. 乐观锁拦截器（总是启用）
 * 
 * 🔧 配置开关：
 * - kexio.auth.mybatis-plus.enabled=true/false (总开关，默认true)
 * - kexio.auth.mybatis-plus.pagination.enabled=true/false (分页开关，默认true)
 * - kexio.auth.mybatis-plus.optimistic-lock.enabled=true/false (乐观锁开关，默认true)
 * - kexio.auth.mybatis-plus.tenant.enabled=auto/true/false (租户开关，默认auto)
 * 
 * @author Kexio Team
 * @since 3.0.0
 */
@Configuration
@ConditionalOnClass({MybatisPlusInterceptor.class})
@ConditionalOnProperty(name = "kexio.auth.mybatis-plus.enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties({MybatisPlusProperties.class})
public class SmartMybatisPlusAutoConfiguration {
    
    private static final Logger logger = LoggerFactory.getLogger(SmartMybatisPlusAutoConfiguration.class);
    
    /**
     * 智能MyBatis-Plus拦截器
     * 
     * 🧠 智能特性：
     * - 自动检测租户配置并决定是否启用租户拦截器
     * - 根据数据库类型自动配置分页拦截器
     * - 支持拦截器的选择性启用/禁用
     * - 优化拦截器顺序以获得最佳性能
     */
    @Bean
    @Primary
    public MybatisPlusInterceptor smartMybatisPlusInterceptor(
            MybatisPlusProperties mybatisProperties,
            ObjectProvider<TenantModeProperties> tenantPropertiesProvider,
            ObjectProvider<FlexibleTenantLineHandler> tenantHandlerProvider) {
        
        logger.info("🚀 初始化智能MyBatis-Plus拦截器配置");
        
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 🛡️ 1. 数据权限拦截器 - 业务权限过滤（最高优先级）
        addDataScopeInterceptorIfNeeded(interceptor, mybatisProperties);
        
        // 🎯 2. 租户拦截器 - 租户数据隔离（第二优先级）
        addTenantInterceptorIfNeeded(interceptor, mybatisProperties, 
                                   tenantPropertiesProvider.getIfAvailable(), 
                                   tenantHandlerProvider.getIfAvailable());
        
        // 📄 3. 分页拦截器 - 分页功能（第三优先级）
        addPaginationInterceptorIfNeeded(interceptor, mybatisProperties);
        
        // 🔒 4. 乐观锁拦截器 - 并发控制（最低优先级）
        addOptimisticLockInterceptorIfNeeded(interceptor, mybatisProperties);
        
        logger.info("✅ 智能MyBatis-Plus拦截器配置完成，共 {} 个拦截器", 
                   interceptor.getInterceptors().size());
        
        return interceptor;
    }
    
    /**
     * 基础字段自动填充处理器
     */
    @Bean
    @ConditionalOnProperty(name = "kexio.auth.mybatis-plus.meta-handler.enabled", havingValue = "true", matchIfMissing = true)
    public MetaObjectHandler smartMetaObjectHandler() {
        logger.info("📝 注册智能字段自动填充处理器");
        return new BaseFieldsMetaObjectHandler();
    }
    
    // ❌ JWT架构下已删除：数据权限拦截器简化，不再需要复杂的MyBatis拦截器
    /*
     * 数据权限拦截器（独立注册）
     * 
     * 注意：DataScopeInterceptor 实现的是原生MyBatis的Interceptor接口，
     * 不是MyBatis-Plus的InnerInterceptor，所以需要单独注册为Spring Bean。
     * 
     * JWT架构下已简化：数据权限通过JWT内置权限和拦截器处理，不再需要复杂的MyBatis拦截器
     */
    /*
    @Bean
    @ConditionalOnProperty(name = "kexio.auth.mybatis-plus.data-scope.enabled", havingValue = "true", matchIfMissing = true)
    public HighPerformanceDataScopeInterceptor smartDataScopeInterceptor(MybatisPlusProperties mybatisProperties) {
        logger.info("🛡️ 注册高性能数据权限拦截器");
        
        HighPerformanceDataScopeInterceptor interceptor = new HighPerformanceDataScopeInterceptor();
        
        // 配置调试模式
        if (mybatisProperties.getDataScope().isDebug()) {
            logger.info("🛡️ 高性能数据权限拦截器启用调试模式");
            // 通过Properties配置调试模式
            java.util.Properties props = new java.util.Properties();
            props.setProperty("enabled", "true");
            props.setProperty("debugMode", "true");
            interceptor.setProperties(props);
        } else {
            // 设置默认配置
            java.util.Properties props = new java.util.Properties();
            props.setProperty("enabled", "true");
            props.setProperty("debugMode", "false");
            interceptor.setProperties(props);
        }
        
        return interceptor;
    }
    */
    
    /**
     * 占位方法：数据权限拦截器已独立注册
     */
    private void addDataScopeInterceptorIfNeeded(MybatisPlusInterceptor interceptor, MybatisPlusProperties mybatisProperties) {
        // DataScopeInterceptor 作为独立的MyBatis拦截器注册，不添加到MybatisPlusInterceptor中
        logger.debug("🛡️ 数据权限拦截器独立注册，执行顺序：DataScope -> MyBatis-Plus拦截器链");
    }
    
    /**
     * 智能添加租户拦截器
     */
    private void addTenantInterceptorIfNeeded(MybatisPlusInterceptor interceptor,
                                            MybatisPlusProperties mybatisProperties,
                                            TenantModeProperties tenantProperties,
                                            FlexibleTenantLineHandler tenantHandler) {
        
        // 检查是否应该启用租户拦截器
        if (!shouldEnableTenantInterceptor(mybatisProperties, tenantProperties)) {
            logger.debug("🏠 租户拦截器未启用，跳过配置");
            return;
        }
        
        if (tenantHandler == null) {
            logger.warn("⚠️ 租户模式已启用但未找到 FlexibleTenantLineHandler，跳过租户拦截器");
            return;
        }
        
        TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
        tenantInterceptor.setTenantLineHandler(tenantHandler);
        interceptor.addInnerInterceptor(tenantInterceptor);
        
        logger.info("🏠 已启用租户拦截器 (模式: {})", 
                   tenantProperties != null ? tenantProperties.getMode() : "未知");
    }
    
    /**
     * 智能添加分页拦截器
     */
    private void addPaginationInterceptorIfNeeded(MybatisPlusInterceptor interceptor, MybatisPlusProperties mybatisProperties) {
        if (!mybatisProperties.getPagination().isEnabled()) {
            logger.debug("📄 分页拦截器已禁用，跳过配置");
            return;
        }
        
        PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.POSTGRE_SQL);
        
        // 智能配置分页参数
        long maxLimit = mybatisProperties.getPagination().getMaxLimit();
        boolean overflow = mybatisProperties.getPagination().isOverflow();
        
        paginationInterceptor.setMaxLimit(maxLimit);
        paginationInterceptor.setOverflow(overflow);
        
        interceptor.addInnerInterceptor(paginationInterceptor);
        logger.info("📄 已启用分页拦截器 (maxLimit: {}, overflow: {})", maxLimit, overflow);
    }
    
    /**
     * 智能添加乐观锁拦截器
     */
    private void addOptimisticLockInterceptorIfNeeded(MybatisPlusInterceptor interceptor, MybatisPlusProperties mybatisProperties) {
        if (!mybatisProperties.getOptimisticLock().isEnabled()) {
            logger.debug("🔒 乐观锁拦截器已禁用，跳过配置");
            return;
        }
        
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        logger.info("🔒 已启用乐观锁拦截器");
    }
    
    /**
     * 智能判断是否启用租户拦截器
     */
    private boolean shouldEnableTenantInterceptor(MybatisPlusProperties mybatisProperties, TenantModeProperties tenantProperties) {
        // 配置优先级：明确配置 > 自动检测
        String explicitSetting = mybatisProperties.getTenant().getEnabled();
        
        switch (explicitSetting.toLowerCase()) {
            case "true":
                return true;
            case "false":
                return false;
            case "auto":
            default:
                return autoDetectTenantInterceptorNeeded(tenantProperties);
        }
    }
    
    /**
     * 自动检测是否需要租户拦截器
     */
    private boolean autoDetectTenantInterceptorNeeded(TenantModeProperties tenantProperties) {
        if (tenantProperties == null || !tenantProperties.isEnabled()) {
            return false;
        }
        
        TenantMode mode = tenantProperties.getMode();
        return mode == TenantMode.ROW_LEVEL || mode == TenantMode.HYBRID;
    }
}
